vulkan: Better glyph cache api
authorMatthias Clasen <mclasen@redhat.com>
Tue, 19 Sep 2017 22:53:32 +0000 (18:53 -0400)
committerMatthias Clasen <mclasen@redhat.com>
Thu, 21 Sep 2017 03:26:14 +0000 (23:26 -0400)
Move the glyph caching api to something that can support using
multiple textures. We now split the text render ops into multiple
ops for different textures, and make each op render just a substring
of the text node's glyph string.

gsk/gskvulkancolortextpipeline.c
gsk/gskvulkancolortextpipelineprivate.h
gsk/gskvulkanrenderer.c
gsk/gskvulkanrendererprivate.h
gsk/gskvulkanrenderpass.c
gsk/gskvulkantextpipeline.c
gsk/gskvulkantextpipelineprivate.h

index 6cca24334e1f79478b120912d15fc86c32fca7f4..6f97a8d6968693ccc5ba44c0beecbda6abe274a0 100644 (file)
@@ -99,15 +99,19 @@ gsk_vulkan_color_text_pipeline_collect_vertex_data (GskVulkanColorTextPipeline *
                                                     PangoFont                  *font,
                                                     PangoGlyphString           *glyphs,
                                                     float                       x,
-                                                    float                       y)
+                                                    float                       y,
+                                                    guint                       start_glyph,
+                                                    guint                       num_glyphs)
 {
   GskVulkanColorTextInstance *instances = (GskVulkanColorTextInstance *) data;
-  int i, count;
+  int i
+  int count = 0;
   int x_position = 0;
-  float dx, dy, dw, dh;
 
-  count = 0;
-  for (i = 0; i < glyphs->num_glyphs; i++)
+  for (i = 0; i < start_glyph; i++)
+    x_position += glyphs->glyphs[i].geometry.width;
+
+  for (; i < num_glyphs; i++)
     {
       PangoGlyphInfo *gi = &glyphs->glyphs[i];
 
@@ -119,17 +123,19 @@ gsk_vulkan_color_text_pipeline_collect_vertex_data (GskVulkanColorTextPipeline *
           if (!(gi->glyph & PANGO_GLYPH_UNKNOWN_FLAG))
             {
               GskVulkanColorTextInstance *instance = &instances[count];
+              GskVulkanCachedGlyph *glyph;
+
+              glyph = gsk_vulkan_renderer_get_cached_glyph (renderer, font, gi->glyph);
+
+              instance->tex_rect[0] = glyph->tx;
+              instance->tex_rect[1] = glyph->ty;
+              instance->tex_rect[2] = glyph->tw;
+              instance->tex_rect[3] = glyph->th;
 
-              gsk_vulkan_renderer_get_glyph_coords (renderer, font, gi->glyph,
-                                                    &instance->tex_rect[0],
-                                                    &instance->tex_rect[1],
-                                                    &instance->tex_rect[2],
-                                                    &instance->tex_rect[3],
-                                                    &dx, &dy, &dw, &dh);
-              instance->rect[0] = x + cx + dx;
-              instance->rect[1] = y + cy + dy;
-              instance->rect[2] = dw;
-              instance->rect[3] = dh;
+              instance->rect[0] = x + cx + glyph->draw_x;
+              instance->rect[1] = y + cy + glyph->draw_y;
+              instance->rect[2] = glyph->draw_width;
+              instance->rect[3] = glyph->draw_height;
 
               count++;
            }
index b341abde34c07bdfd8d6b04165060158c710dced..8c4a8c35c428b0a7a8f752d2af09c17d57d9494b 100644 (file)
@@ -27,7 +27,9 @@ void                    gsk_vulkan_color_text_pipeline_collect_vertex_data   (Gs
                                                                               PangoFont                      *font,
                                                                               PangoGlyphString               *glyphs,
                                                                               float                           x,
-                                                                              float                           y);
+                                                                              float                           y,
+                                                                              guint                           start_glyph,
+                                                                              guint                           num_glyphs);
 gsize                   gsk_vulkan_color_text_pipeline_draw                  (GskVulkanColorTextPipeline     *pipeline,
                                                                               VkCommandBuffer                 command_buffer,
                                                                               gsize                           offset,
index d9739a02ccef9d4f1fe0552d1bd84f9eef7b03b6..281bc2215e728f415ec193ef24f77a4c969b9432 100644 (file)
@@ -370,22 +370,6 @@ gsk_vulkan_renderer_ref_texture_image (GskVulkanRenderer *self,
   return image;
 }
 
-GskVulkanImage *
-gsk_vulkan_renderer_ref_glyph_image (GskVulkanRenderer  *self,
-                                     GskVulkanUploader  *uploader,
-                                     PangoFont          *font,
-                                     PangoGlyphString   *glyphs)
-{
-  if (self->glyph_cache->image == NULL)
-    self->glyph_cache->image = gsk_vulkan_image_new_from_data (uploader,
-                                    cairo_image_surface_get_data (self->glyph_cache->surface),
-                                    cairo_image_surface_get_width (self->glyph_cache->surface),
-                                    cairo_image_surface_get_height (self->glyph_cache->surface),
-                                    cairo_image_surface_get_stride (self->glyph_cache->surface));
-
-  return g_object_ref (self->glyph_cache->image);
-}
-
 typedef struct _GlyphCacheKey GlyphCacheKey;
 typedef struct _GlyphCacheValue GlyphCacheValue;
 
@@ -394,53 +378,6 @@ struct _GlyphCacheKey {
   PangoGlyph glyph;
 };
 
-struct _GlyphCacheValue {
-  float tx;
-  float ty;
-  float tw;
-  float th;
-
-  float draw_x;
-  float draw_y;
-  float draw_width;
-  float draw_height;
-};
-
-static GlyphCacheValue *glyph_cache_lookup (GlyphCache *cache,
-                                            gboolean    create,
-                                            PangoFont  *font,
-                                            PangoGlyph  glyph);
-
-void
-gsk_vulkan_renderer_get_glyph_coords (GskVulkanRenderer *self,
-                                      PangoFont         *font,
-                                      PangoGlyph         glyph,
-                                      float             *tx,
-                                      float             *ty,
-                                      float             *tw,
-                                      float             *th,
-                                      float             *dx,
-                                      float             *dy,
-                                      float             *dw,
-                                      float             *dh)
-{
-  GlyphCacheValue *gv;
-
-  gv = glyph_cache_lookup (self->glyph_cache, FALSE, font, glyph);
-
-  if (gv)
-    {
-      *tx = gv->tx;
-      *ty = gv->ty;
-      *tw = gv->tw;
-      *th = gv->th;
-      *dx = gv->draw_x;
-      *dy = gv->draw_y;
-      *dw = gv->draw_width;
-      *dh = gv->draw_height;
-    }
-}
-
 /*** Glyph cache ***/
 
 static gboolean
@@ -477,10 +414,10 @@ glyph_cache_value_free (gpointer v)
 }
 
 static void
-add_to_cache (GlyphCache      *cache,
-              PangoFont       *font,
-              PangoGlyph       glyph,
-              GlyphCacheValue *value)
+add_to_cache (GlyphCache           *cache,
+              PangoFont            *font,
+              PangoGlyph            glyph,
+              GskVulkanCachedGlyph *value)
 {
   cairo_t *cr;
   cairo_scaled_font_t *scaled_font;
@@ -523,16 +460,18 @@ add_to_cache (GlyphCache      *cache,
   value->ty = (cg.y + value->draw_y) / cache->height;
   value->tw = (float)value->draw_width / cache->width;
   value->th = (float)value->draw_height / cache->height;
+
+  value->texture_index = 0;
 }
 
-static GlyphCacheValue *
+static GskVulkanCachedGlyph *
 glyph_cache_lookup (GlyphCache *cache,
                     gboolean    create,
                     PangoFont  *font,
                     PangoGlyph  glyph)
 {
   GlyphCacheKey lookup_key;
-  GlyphCacheValue *value;
+  GskVulkanCachedGlyph *value;
 
   lookup_key.font = font;
   lookup_key.glyph = glyph;
@@ -544,7 +483,9 @@ glyph_cache_lookup (GlyphCache *cache,
       GlyphCacheKey *key;
       PangoRectangle ink_rect;
 
-      value = g_new (GlyphCacheValue, 1);
+      value = g_new (GskVulkanCachedGlyph, 1);
+
+      value->texture_index = 0;
 
       pango_font_get_glyph_extents (font, glyph, &ink_rect, NULL);
       pango_extents_to_pixels (&ink_rect, NULL);
@@ -555,11 +496,7 @@ glyph_cache_lookup (GlyphCache *cache,
       value->draw_height = ink_rect.height;
 
       if (ink_rect.width > 0 && ink_rect.height > 0)
-        {
-          add_to_cache (cache, font, glyph, value);
-
-          g_clear_object (&cache->image);
-        }
+        add_to_cache (cache, font, glyph, value);
 
       key = g_new (GlyphCacheKey, 1);
       key->font = g_object_ref (font);
@@ -571,23 +508,42 @@ glyph_cache_lookup (GlyphCache *cache,
   return value;
 }
 
-void
-gsk_vulkan_renderer_cache_glyphs (GskVulkanRenderer *self,
-                                  PangoFont         *font,
-                                  PangoGlyphString  *glyphs)
+static void
+free_glyph_cache (GlyphCache *cache)
+{
+  g_hash_table_unref (cache->hash_table);
+  cairo_surface_destroy (cache->surface);
+  g_free (cache);
+}
+
+static void
+dump_glyph_cache_stats (GlyphCache *cache)
 {
-  int i;
+  static gint64 time;
+  gint64 now;
 
-  for (i = 0; i < glyphs->num_glyphs; i++)
-    {
-      PangoGlyphInfo *gi = &glyphs->glyphs[i];
+  if (!cache->hash_table)
+    return;
 
-      if (gi->glyph != PANGO_GLYPH_EMPTY)
-        {
-          if (!(gi->glyph & PANGO_GLYPH_UNKNOWN_FLAG))
-            (void) glyph_cache_lookup (self->glyph_cache, TRUE, font, gi->glyph);
-        }
-    }
+  now = g_get_monotonic_time ();
+  if (now - time < 1000000)
+    return;
+
+  time = now;
+
+  cairo_surface_write_to_png (cache->surface, "gsk-glyph-cache.png");
+}
+
+guint
+gsk_vulkan_renderer_cache_glyph (GskVulkanRenderer *self,
+                                 PangoFont         *font,
+                                 PangoGlyph         glyph)
+{
+  GskVulkanCachedGlyph *value;
+
+  value = glyph_cache_lookup (self->glyph_cache, TRUE, font, glyph);
+
+  return value->texture_index;
 }
 
 static GlyphCache *
@@ -608,28 +564,30 @@ create_glyph_cache (void)
   return cache;
 }
 
-static void
-free_glyph_cache (GlyphCache *cache)
+GskVulkanImage *
+gsk_vulkan_renderer_ref_glyph_image (GskVulkanRenderer  *self,
+                                     GskVulkanUploader  *uploader,
+                                     guint               index)
 {
-  g_hash_table_unref (cache->hash_table);
-  cairo_surface_destroy (cache->surface);
-  g_free (cache);
+  if (self->glyph_cache->image == NULL)
+    self->glyph_cache->image = gsk_vulkan_image_new_from_data (uploader,
+                                    cairo_image_surface_get_data (self->glyph_cache->surface),
+                                    cairo_image_surface_get_width (self->glyph_cache->surface),
+                                    cairo_image_surface_get_height (self->glyph_cache->surface),
+                                    cairo_image_surface_get_stride (self->glyph_cache->surface));
+
+  return g_object_ref (self->glyph_cache->image);
 }
 
-static void
-dump_glyph_cache_stats (GlyphCache *cache)
+GskVulkanCachedGlyph *
+gsk_vulkan_renderer_get_cached_glyph (GskVulkanRenderer *self,
+                                      PangoFont         *font,
+                                      PangoGlyph         glyph)
 {
-  static gint64 time;
-  gint64 now;
-
-  if (!cache->hash_table)
-    return;
-
-  now = g_get_monotonic_time ();
-  if (now - time < 1000000)
-    return;
+  GlyphCacheKey lookup_key;
 
-  time = now;
+  lookup_key.font = font;
+  lookup_key.glyph = glyph;
 
-  cairo_surface_write_to_png (cache->surface, "gsk-glyph-cache.png");
+  return g_hash_table_lookup (self->glyph_cache->hash_table, &lookup_key);
 }
index 25b90e6c299257c6e213528be84c33dab20ef635..0f954e3cbbd8ea0acf9bbb219c1482ac0fa8d631 100644 (file)
@@ -25,26 +25,33 @@ GskVulkanImage *        gsk_vulkan_renderer_ref_texture_image           (GskVulk
                                                                          GskTexture             *texture,
                                                                          GskVulkanUploader      *uploader);
 
-GskVulkanImage *        gsk_vulkan_renderer_ref_glyph_image             (GskVulkanRenderer      *self,
-                                                                         GskVulkanUploader      *uploader,
-                                                                         PangoFont              *font,
-                                                                         PangoGlyphString       *glyphs);
-
-void                    gsk_vulkan_renderer_get_glyph_coords            (GskVulkanRenderer      *self,
-                                                                         PangoFont              *font,
-                                                                         PangoGlyph              glyph,
-                                                                         float                  *tx,
-                                                                         float                  *ty,
-                                                                         float                  *tw,
-                                                                         float                  *th,
-                                                                         float                  *dx,
-                                                                         float                  *dy,
-                                                                         float                  *dw,
-                                                                         float                  *dh);
-
-void                    gsk_vulkan_renderer_cache_glyphs                (GskVulkanRenderer      *renderer,
-                                                                         PangoFont              *font,
-                                                                         PangoGlyphString       *glyphs);
+typedef struct
+{
+  guint texture_index;
+
+  float tx;
+  float ty;
+  float tw;
+  float th;
+
+  int draw_x;
+  int draw_y;
+  int draw_width;
+  int draw_height;
+} GskVulkanCachedGlyph;
+
+guint                  gsk_vulkan_renderer_cache_glyph      (GskVulkanRenderer *renderer,
+                                                             PangoFont         *font,
+                                                             PangoGlyph         glyph);
+
+GskVulkanImage *       gsk_vulkan_renderer_ref_glyph_image  (GskVulkanRenderer *self,
+                                                             GskVulkanUploader *uploader,
+                                                             guint              index);
+
+GskVulkanCachedGlyph * gsk_vulkan_renderer_get_cached_glyph (GskVulkanRenderer *self,
+                                                             PangoFont         *font,
+                                                             PangoGlyph         glyph);
+
 
 G_END_DECLS
 
index 1c22f233f55727f96933dcbddf44ba9a223cdde2..d6dc158231904c64052071ed79144e5301a62b42 100644 (file)
@@ -25,6 +25,7 @@
 
 typedef union _GskVulkanOp GskVulkanOp;
 typedef struct _GskVulkanOpRender GskVulkanOpRender;
+typedef struct _GskVulkanOpText GskVulkanOpText;
 typedef struct _GskVulkanOpPushConstants GskVulkanOpPushConstants;
 
 typedef enum {
@@ -60,6 +61,21 @@ struct _GskVulkanOpRender
   gsize                descriptor_set_index; /* index into descriptor sets array for the right descriptor set to bind */
 };
 
+struct _GskVulkanOpText
+{
+  GskVulkanOpType      type;
+  GskRenderNode       *node; /* node that's the source of this op */
+  GskVulkanPipeline   *pipeline; /* pipeline to use */
+  GskRoundedRect       clip; /* clip rect (or random memory if not relevant) */
+  GskVulkanImage      *source; /* source image to render */
+  gsize                vertex_offset; /* offset into vertex buffer */
+  gsize                vertex_count; /* number of vertices */
+  gsize                descriptor_set_index; /* index into descriptor sets array for the right descriptor set to bind */
+  guint                texture_index;
+  guint                start_glyph;
+  guint                num_glyphs;
+};
+
 struct _GskVulkanOpPushConstants
 {
   GskVulkanOpType         type;
@@ -72,6 +88,7 @@ union _GskVulkanOp
   GskVulkanOpType          type;
   GskVulkanOpRender        render;
   GskVulkanOpPushConstants constants;
+  GskVulkanOpText          text;
 };
 
 struct _GskVulkanRenderPass
@@ -197,37 +214,59 @@ gsk_vulkan_render_pass_add_node (GskVulkanRenderPass           *self,
       return;
 
     case GSK_TEXT_NODE:
-       gsk_vulkan_renderer_cache_glyphs (GSK_VULKAN_RENDERER (gsk_vulkan_render_get_renderer (render)),
-                                         gsk_text_node_get_font (node),
-                                         gsk_text_node_get_glyphs (node));
+      {
+        PangoFont *font = gsk_text_node_get_font (node);
+        PangoGlyphString *glyphs = gsk_text_node_get_glyphs (node);
+        PangoGlyph glyph;
+        int i;
+        guint texture_index;
+        GskVulkanRenderer *renderer = GSK_VULKAN_RENDERER (gsk_vulkan_render_get_renderer (render));
+
+        if (font_has_color_glyphs (font))
+          {
+            if (gsk_vulkan_clip_contains_rect (&constants->clip, &node->bounds))
+              pipeline_type = GSK_VULKAN_PIPELINE_COLOR_TEXT;
+            else if (constants->clip.type == GSK_VULKAN_CLIP_RECT)
+              pipeline_type = GSK_VULKAN_PIPELINE_COLOR_TEXT_CLIP;
+            else if (constants->clip.type == GSK_VULKAN_CLIP_ROUNDED_CIRCULAR)
+              pipeline_type = GSK_VULKAN_PIPELINE_COLOR_TEXT_CLIP_ROUNDED;
+            else
+              FALLBACK ("Text nodes can't deal with clip type %u\n", constants->clip.type);
+            op.type = GSK_VULKAN_OP_COLOR_TEXT;
+          }
+        else
+          {
+            if (gsk_vulkan_clip_contains_rect (&constants->clip, &node->bounds))
+              pipeline_type = GSK_VULKAN_PIPELINE_TEXT;
+            else if (constants->clip.type == GSK_VULKAN_CLIP_RECT)
+              pipeline_type = GSK_VULKAN_PIPELINE_TEXT_CLIP;
+            else if (constants->clip.type == GSK_VULKAN_CLIP_ROUNDED_CIRCULAR)
+              pipeline_type = GSK_VULKAN_PIPELINE_TEXT_CLIP_ROUNDED;
+            else
+              FALLBACK ("Text nodes can't deal with clip type %u\n", constants->clip.type);
+            op.type = GSK_VULKAN_OP_TEXT;
+          }
+        op.text.pipeline = gsk_vulkan_render_get_pipeline (render, pipeline_type);
 
-      if (font_has_color_glyphs (gsk_text_node_get_font (node)))
-        {
-          if (gsk_vulkan_clip_contains_rect (&constants->clip, &node->bounds))
-            pipeline_type = GSK_VULKAN_PIPELINE_COLOR_TEXT;
-          else if (constants->clip.type == GSK_VULKAN_CLIP_RECT)
-            pipeline_type = GSK_VULKAN_PIPELINE_COLOR_TEXT_CLIP;
-          else if (constants->clip.type == GSK_VULKAN_CLIP_ROUNDED_CIRCULAR)
-            pipeline_type = GSK_VULKAN_PIPELINE_COLOR_TEXT_CLIP_ROUNDED;
-          else
-            FALLBACK ("Text nodes can't deal with clip type %u\n", constants->clip.type);
-          op.type = GSK_VULKAN_OP_COLOR_TEXT;
-        }
-      else
-        {
-          if (gsk_vulkan_clip_contains_rect (&constants->clip, &node->bounds))
-            pipeline_type = GSK_VULKAN_PIPELINE_TEXT;
-          else if (constants->clip.type == GSK_VULKAN_CLIP_RECT)
-            pipeline_type = GSK_VULKAN_PIPELINE_TEXT_CLIP;
-          else if (constants->clip.type == GSK_VULKAN_CLIP_ROUNDED_CIRCULAR)
-            pipeline_type = GSK_VULKAN_PIPELINE_TEXT_CLIP_ROUNDED;
-          else
-            FALLBACK ("Text nodes can't deal with clip type %u\n", constants->clip.type);
-          op.type = GSK_VULKAN_OP_TEXT;
-        }
-      op.render.pipeline = gsk_vulkan_render_get_pipeline (render, pipeline_type);
-      g_array_append_val (self->render_ops, op);
-      return;
+        i = 0;
+        texture_index = gsk_vulkan_renderer_cache_glyph (renderer, font, glyphs->glyphs[0].glyph);
+        while (i < glyphs->num_glyphs)
+          {
+            op.text.start_glyph = i;
+            op.text.texture_index = texture_index;
+
+            do {
+              i++;
+              glyph = glyphs->glyphs[i].glyph;
+              if (glyph != PANGO_GLYPH_EMPTY && !(glyph & PANGO_GLYPH_UNKNOWN_FLAG))
+                texture_index = gsk_vulkan_renderer_cache_glyph (renderer, font, glyph);
+            } while (i < glyphs->num_glyphs && op.text.texture_index == texture_index);
+
+            op.text.num_glyphs = i - op.text.start_glyph;
+            g_array_append_val (self->render_ops, op);
+          }
+        return;
+      }
 
     case GSK_TEXTURE_NODE:
       if (gsk_vulkan_clip_contains_rect (&constants->clip, &node->bounds))
@@ -600,11 +639,10 @@ gsk_vulkan_render_pass_upload (GskVulkanRenderPass  *self,
         case GSK_VULKAN_OP_TEXT:
         case GSK_VULKAN_OP_COLOR_TEXT:
           {
-            op->render.source = gsk_vulkan_renderer_ref_glyph_image (GSK_VULKAN_RENDERER (gsk_vulkan_render_get_renderer (render)),
-                                                                     uploader,
-                                                                     gsk_text_node_get_font (op->render.node),
-                                                                     gsk_text_node_get_glyphs (op->render.node));
-            gsk_vulkan_render_add_cleanup_image (render, op->render.source);
+            op->text.source = gsk_vulkan_renderer_ref_glyph_image (GSK_VULKAN_RENDERER (gsk_vulkan_render_get_renderer (render)),
+                                                                   uploader,
+                                                                   op->text.texture_index);
+            gsk_vulkan_render_add_cleanup_image (render, op->text.source);
           }
           break;
 
@@ -690,15 +728,15 @@ gsk_vulkan_render_pass_count_vertex_data (GskVulkanRenderPass *self)
           break;
 
         case GSK_VULKAN_OP_TEXT:
-          op->render.vertex_count = gsk_vulkan_text_pipeline_count_vertex_data (GSK_VULKAN_TEXT_PIPELINE (op->render.pipeline),
-                                                                                pango_glyph_string_num_glyphs (gsk_text_node_get_glyphs (op->render.node)));
-          n_bytes += op->render.vertex_count;
+          op->text.vertex_count = gsk_vulkan_text_pipeline_count_vertex_data (GSK_VULKAN_TEXT_PIPELINE (op->text.pipeline),
+                                                                              op->text.num_glyphs);
+          n_bytes += op->text.vertex_count;
           break;
 
         case GSK_VULKAN_OP_COLOR_TEXT:
-          op->render.vertex_count = gsk_vulkan_color_text_pipeline_count_vertex_data (GSK_VULKAN_COLOR_TEXT_PIPELINE (op->render.pipeline),
-                                                                                      pango_glyph_string_num_glyphs (gsk_text_node_get_glyphs (op->render.node)));
-          n_bytes += op->render.vertex_count;
+          op->text.vertex_count = gsk_vulkan_color_text_pipeline_count_vertex_data (GSK_VULKAN_COLOR_TEXT_PIPELINE (op->render.pipeline),
+                                                                                    op->text.num_glyphs);
+          n_bytes += op->text.vertex_count;
           break;
 
         case GSK_VULKAN_OP_COLOR:
@@ -777,32 +815,36 @@ gsk_vulkan_render_pass_collect_vertex_data (GskVulkanRenderPass *self,
 
         case GSK_VULKAN_OP_TEXT:
           {
-            op->render.vertex_offset = offset + n_bytes;
-            gsk_vulkan_text_pipeline_collect_vertex_data (GSK_VULKAN_TEXT_PIPELINE (op->render.pipeline),
+            op->text.vertex_offset = offset + n_bytes;
+            gsk_vulkan_text_pipeline_collect_vertex_data (GSK_VULKAN_TEXT_PIPELINE (op->text.pipeline),
                                                           data + n_bytes + offset,
                                                           GSK_VULKAN_RENDERER (gsk_vulkan_render_get_renderer (render)),
-                                                          &op->render.node->bounds,
-                                                          gsk_text_node_get_font (op->render.node),
-                                                          gsk_text_node_get_glyphs (op->render.node),
-                                                          gsk_text_node_get_color (op->render.node),
-                                                          gsk_text_node_get_x (op->render.node),
-                                                          gsk_text_node_get_y (op->render.node));
-            n_bytes += op->render.vertex_count;
+                                                          &op->text.node->bounds,
+                                                          gsk_text_node_get_font (op->text.node),
+                                                          gsk_text_node_get_glyphs (op->text.node),
+                                                          gsk_text_node_get_color (op->text.node),
+                                                          gsk_text_node_get_x (op->text.node),
+                                                          gsk_text_node_get_y (op->text.node),
+                                                          op->text.start_glyph,
+                                                          op->text.num_glyphs);
+            n_bytes += op->text.vertex_count;
           }
           break;
 
         case GSK_VULKAN_OP_COLOR_TEXT:
           {
-            op->render.vertex_offset = offset + n_bytes;
-            gsk_vulkan_color_text_pipeline_collect_vertex_data (GSK_VULKAN_COLOR_TEXT_PIPELINE (op->render.pipeline),
+            op->text.vertex_offset = offset + n_bytes;
+            gsk_vulkan_color_text_pipeline_collect_vertex_data (GSK_VULKAN_COLOR_TEXT_PIPELINE (op->text.pipeline),
                                                                 data + n_bytes + offset,
                                                                 GSK_VULKAN_RENDERER (gsk_vulkan_render_get_renderer (render)),
-                                                                &op->render.node->bounds,
-                                                                gsk_text_node_get_font (op->render.node),
-                                                                gsk_text_node_get_glyphs (op->render.node),
-                                                                gsk_text_node_get_x (op->render.node),
-                                                                gsk_text_node_get_y (op->render.node));
-            n_bytes += op->render.vertex_count;
+                                                                &op->text.node->bounds,
+                                                                gsk_text_node_get_font (op->text.node),
+                                                                gsk_text_node_get_glyphs (op->text.node),
+                                                                gsk_text_node_get_x (op->text.node),
+                                                                gsk_text_node_get_y (op->text.node),
+                                                                op->text.start_glyph,
+                                                                op->text.num_glyphs);
+            n_bytes += op->text.vertex_count;
           }
           break;
 
@@ -948,8 +990,6 @@ gsk_vulkan_render_pass_reserve_descriptor_sets (GskVulkanRenderPass *self,
         case GSK_VULKAN_OP_FALLBACK_CLIP:
         case GSK_VULKAN_OP_FALLBACK_ROUNDED_CLIP:
         case GSK_VULKAN_OP_SURFACE:
-        case GSK_VULKAN_OP_TEXT:
-        case GSK_VULKAN_OP_COLOR_TEXT:
         case GSK_VULKAN_OP_TEXTURE:
         case GSK_VULKAN_OP_OPACITY:
         case GSK_VULKAN_OP_BLUR:
@@ -957,6 +997,10 @@ gsk_vulkan_render_pass_reserve_descriptor_sets (GskVulkanRenderPass *self,
           op->render.descriptor_set_index = gsk_vulkan_render_reserve_descriptor_set (render, op->render.source);
           break;
 
+        case GSK_VULKAN_OP_TEXT:
+        case GSK_VULKAN_OP_COLOR_TEXT:
+          op->text.descriptor_set_index = gsk_vulkan_render_reserve_descriptor_set (render, op->text.source);
+          break;
         default:
           g_assert_not_reached ();
         case GSK_VULKAN_OP_COLOR:
@@ -1027,9 +1071,9 @@ gsk_vulkan_render_pass_draw (GskVulkanRenderPass     *self,
           break;
 
         case GSK_VULKAN_OP_TEXT:
-          if (current_pipeline != op->render.pipeline)
+          if (current_pipeline != op->text.pipeline)
             {
-              current_pipeline = op->render.pipeline;
+              current_pipeline = op->text.pipeline;
               vkCmdBindPipeline (command_buffer,
                                  VK_PIPELINE_BIND_POINT_GRAPHICS,
                                  gsk_vulkan_pipeline_get_pipeline (current_pipeline));
@@ -1039,7 +1083,7 @@ gsk_vulkan_render_pass_draw (GskVulkanRenderPass     *self,
                                       (VkBuffer[1]) {
                                           gsk_vulkan_buffer_get_buffer (vertex_buffer)
                                       },
-                                      (VkDeviceSize[1]) { op->render.vertex_offset });
+                                      (VkDeviceSize[1]) { op->text.vertex_offset });
               current_draw_index = 0;
             }
 
@@ -1049,20 +1093,20 @@ gsk_vulkan_render_pass_draw (GskVulkanRenderPass     *self,
                                    0,
                                    1,
                                    (VkDescriptorSet[1]) {
-                                       gsk_vulkan_render_get_descriptor_set (render, op->render.descriptor_set_index)
+                                       gsk_vulkan_render_get_descriptor_set (render, op->text.descriptor_set_index)
                                    },
                                    0,
                                    NULL);
 
           current_draw_index += gsk_vulkan_text_pipeline_draw (GSK_VULKAN_TEXT_PIPELINE (current_pipeline),
-                                                                command_buffer,
-                                                                current_draw_index, pango_glyph_string_num_glyphs (gsk_text_node_get_glyphs (op->render.node)));
+                                                               command_buffer,
+                                                               current_draw_index, op->text.num_glyphs);
           break;
 
         case GSK_VULKAN_OP_COLOR_TEXT:
-          if (current_pipeline != op->render.pipeline)
+          if (current_pipeline != op->text.pipeline)
             {
-              current_pipeline = op->render.pipeline;
+              current_pipeline = op->text.pipeline;
               vkCmdBindPipeline (command_buffer,
                                  VK_PIPELINE_BIND_POINT_GRAPHICS,
                                  gsk_vulkan_pipeline_get_pipeline (current_pipeline));
@@ -1072,7 +1116,7 @@ gsk_vulkan_render_pass_draw (GskVulkanRenderPass     *self,
                                       (VkBuffer[1]) {
                                           gsk_vulkan_buffer_get_buffer (vertex_buffer)
                                       },
-                                      (VkDeviceSize[1]) { op->render.vertex_offset });
+                                      (VkDeviceSize[1]) { op->text.vertex_offset });
               current_draw_index = 0;
             }
 
@@ -1082,14 +1126,14 @@ gsk_vulkan_render_pass_draw (GskVulkanRenderPass     *self,
                                    0,
                                    1,
                                    (VkDescriptorSet[1]) {
-                                       gsk_vulkan_render_get_descriptor_set (render, op->render.descriptor_set_index)
+                                       gsk_vulkan_render_get_descriptor_set (render, op->text.descriptor_set_index)
                                    },
                                    0,
                                    NULL);
 
           current_draw_index += gsk_vulkan_color_text_pipeline_draw (GSK_VULKAN_COLOR_TEXT_PIPELINE (current_pipeline),
                                                                      command_buffer,
-                                                                     current_draw_index, pango_glyph_string_num_glyphs (gsk_text_node_get_glyphs (op->render.node)));
+                                                                     current_draw_index, op->text.num_glyphs);
           break;
 
         case GSK_VULKAN_OP_OPACITY:
index def6c6e95fb754d19a54d393f79078c1379e25e4..76c99886890c78899fee028c8691f26a9f8cd3dc 100644 (file)
@@ -107,15 +107,19 @@ gsk_vulkan_text_pipeline_collect_vertex_data (GskVulkanTextPipeline  *pipeline,
                                               PangoGlyphString       *glyphs,
                                               const GdkRGBA          *color,
                                               float                   x,
-                                              float                   y)
+                                              float                   y,
+                                              guint                   start_glyph,
+                                              guint                   num_glyphs)
 {
   GskVulkanTextInstance *instances = (GskVulkanTextInstance *) data;
-  int i, count;
+  int i
+  int count = 0;
   int x_position = 0;
-  float dx, dy, dw, dh;
 
-  count = 0;
-  for (i = 0; i < glyphs->num_glyphs; i++)
+  for (i = 0; i < start_glyph; i++)
+    x_position += glyphs->glyphs[i].geometry.width;
+
+  for (; i < num_glyphs; i++)
     {
       PangoGlyphInfo *gi = &glyphs->glyphs[i];
 
@@ -127,17 +131,19 @@ gsk_vulkan_text_pipeline_collect_vertex_data (GskVulkanTextPipeline  *pipeline,
           if (!(gi->glyph & PANGO_GLYPH_UNKNOWN_FLAG))
             {
               GskVulkanTextInstance *instance = &instances[count];
+              GskVulkanCachedGlyph *glyph;
+
+              glyph = gsk_vulkan_renderer_get_cached_glyph (renderer, font, gi->glyph);
+              instance->tex_rect[0] = glyph->tx;
+              instance->tex_rect[1] = glyph->ty;
+              instance->tex_rect[2] = glyph->tw;
+              instance->tex_rect[3] = glyph->th;
+
+              instance->rect[0] = x + cx + glyph->draw_x;
+              instance->rect[1] = y + cy + glyph->draw_y;
+              instance->rect[2] = glyph->draw_width;
+              instance->rect[3] = glyph->draw_height;
 
-              gsk_vulkan_renderer_get_glyph_coords (renderer, font, gi->glyph,
-                                                    &instance->tex_rect[0],
-                                                    &instance->tex_rect[1],
-                                                    &instance->tex_rect[2],
-                                                    &instance->tex_rect[3],
-                                                    &dx, &dy, &dw, &dh);
-              instance->rect[0] = x + cx + dx;
-              instance->rect[1] = y + cy + dy;
-              instance->rect[2] = dw;
-              instance->rect[3] = dh;
               instance->color[0] = color->red;
               instance->color[1] = color->green;
               instance->color[2] = color->blue;
index a41846d57aad6e79c979f76f94021c24a094c95a..09a58c046890677553ca82a4d626cc4298d4e974 100644 (file)
@@ -28,7 +28,9 @@ void                    gsk_vulkan_text_pipeline_collect_vertex_data   (GskVulka
                                                                         PangoGlyphString               *glyphs,
                                                                         const GdkRGBA                  *color,
                                                                         float                           x,
-                                                                        float                           y);
+                                                                        float                           y,
+                                                                        guint                           start_glyph,
+                                                                        guint                           num_glyphs);
 gsize                   gsk_vulkan_text_pipeline_draw                  (GskVulkanTextPipeline         *pipeline,
                                                                         VkCommandBuffer                 command_buffer,
                                                                         gsize                           offset,